package com.chdz.code.utils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.*;

import org.springframework.util.StringUtils;

/**
 * @Auther: Appet
 * @Date: 2018/7/24 13:26
 * @Description:
 */
import com.chdz.code.model.ColumnClass;

import freemarker.template.Template;

public class CodeGenerateUtils {
	private static final String SUFFIX = ".java";
	private final String AUTHOR = "Appet";
	private static String CURRENT_DATE = "201908月07日 上午9:58:36";
	private final String tableName = "mianyang_gaode_poi";
	private final String modelName = "MyPoi";
	private final String packageName = "com.chdz.common";
	private final String tableAnnotation = "绵阳Poi数据";
	private final String basePath = "E://长虹代码2//";
	private final String diskServerPath =  basePath + "chdz-base-service//base-rest//src//main//java//com//chdz//common//";
	private final String diskGatePath = basePath + "chdz-gateway-service//chdz-gateway-rest//src//main//java//com//chdz//common//";
	private final String changeTableName = replaceUnderLineAndUpperCase(tableName);
	private final Boolean isDB = true;// 关系型数据库为true，如：oracle,mysql;ElasticSearch为false。

	public static void main(String[] args) throws Exception {
		
		CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
		codeGenerateUtils.generate();
	}

	public void generate() throws Exception {
		try {
			// 如果路径的文件夹没生成，需要生成
			generateDirs();
			// 生成Repository文件
			generateRepositoryFile();
			// 生成服务实现层文件
			generateServiceFile();
			// 生成Controller层文件
			generateControllerFile();
			// 生成Model文件
			if (isDB) {
				Map<String, List<ColumnClass>> fields = DBUtils.getFields(tableName);
				generateModelFile(fields);
			} else {
				 Map<String, Map<String, List<ColumnClass>>> fields =
				 ElasticSearchUtils.getFields(tableName+"v1", tableName + "search");
				 Set<String> keys = fields.keySet();
				 for(String key : keys) {
				 	generateModelFileForES(key,fields.get(key));
				 }
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void generateDirs() {

		List<String> filePath = new ArrayList<String>();

		String entityPath = diskServerPath + "mysql//entity";
		filePath.add(entityPath);

		String requestPath = diskServerPath + "request";
		filePath.add(requestPath);

		String responsePath = diskServerPath + "response";
		filePath.add(responsePath);

		String controllerPath = diskServerPath + "controller";
		filePath.add(controllerPath);

		String servicePath = diskServerPath + "service";
		filePath.add(servicePath);

		String repositoryPath = diskServerPath + "mysql//repository";
		filePath.add(repositoryPath);

		String gateControllerPath = diskGatePath + "controller";
		filePath.add(gateControllerPath);

		String gateRequestPath = diskGatePath + "request";
		filePath.add(gateRequestPath);

		String gateResponsePath = diskGatePath + "response";
		filePath.add(gateResponsePath);

		String gateServicePath = diskGatePath + "service";
		filePath.add(gateServicePath);
		
		for(String path : filePath) {
			File file = new File(path);
			if(!file.exists()) {
				file.mkdirs();
			}
		}
	}
	private void generateModelFileForES(String key,Map<String, List<ColumnClass>> fields) throws Exception{
		Map<String, Object> dataMap = new HashMap<>();
		dataMap.put("model_column", fields.get("all"));
		String path = "";
		String templateName = "ModelForES.ftl";
		File mapperFile = null;
		if("main".equals(key)){
			path = diskServerPath + "es//entity//" + modelName + SUFFIX;
			mapperFile = new File(path);
			generateFileByTemplate(templateName, mapperFile, dataMap);
		}else{
			path = diskServerPath + "es//entity//" + key + SUFFIX;
			mapperFile = new File(path);
			dataMap.put("table_name",key);
			dataMap.put("model_name",key);
			dataMap.put("table_annotation","");
			generateFileByTemplate(templateName, mapperFile, dataMap);
		}
	}
	private void generateModelFile(Map<String, List<ColumnClass>> fields) throws Exception {
		Map<String, Object> dataMap = new HashMap<>();
		dataMap.put("model_column", fields.get("all"));
		String path = diskServerPath + "mysql//entity//" + modelName + SUFFIX;
		String templateName = "Model.ftl";
		File mapperFile = new File(path);
		generateFileByTemplate(templateName, mapperFile, dataMap);

		path = diskServerPath + "request//Add" + modelName + "Request" + SUFFIX;
		templateName = "AddPoJo.ftl";
		File addRequest = new File(path);
		dataMap.put("model_column", fields.get("reduce"));
		generateFileByTemplate(templateName, addRequest, dataMap);

		path = diskServerPath + "request//Update" + modelName + "Request" + SUFFIX;
		templateName = "UpdatePoJo.ftl";
		File updateRequest = new File(path);
		dataMap.put("model_column", fields.get("reduce"));
		generateFileByTemplate(templateName, updateRequest, dataMap);

		path = diskServerPath + "response//" + modelName + "Response" + SUFFIX;
		templateName = "Response.ftl";
		File response = new File(path);
		dataMap.put("model_column", fields.get("response"));
		generateFileByTemplate(templateName, response, dataMap);

		// 生成网关
		File gateFile = new File(path);
		generateFileByTemplate(templateName, gateFile, dataMap);

		String gatePath = diskGatePath + "request//Add" + modelName + "Request" + SUFFIX;
		templateName = "AddPoJo.ftl";
		File gateAddRequest = new File(gatePath);
		dataMap.put("model_column", fields.get("reduce"));
		generateFileByTemplate(templateName, gateAddRequest, dataMap);
		gatePath = diskGatePath + "request//Update" + modelName + "Request" + SUFFIX;
		templateName = "UpdatePoJo.ftl";
		File gateUpdateRequest = new File(gatePath);
		dataMap.put("model_column", fields.get("reduce"));
		generateFileByTemplate(templateName, gateUpdateRequest, dataMap);
		gatePath = diskGatePath + "response//" + modelName + "Response" + SUFFIX;
		templateName = "Response.ftl";
		File gateResponse = new File(gatePath);
		dataMap.put("model_column", fields.get("response"));
		generateFileByTemplate(templateName, gateResponse, dataMap);
	}

	private void generateControllerFile() throws Exception {
		// 生成服务端Controller
		String path = diskServerPath + "controller//" + modelName + "Controller" + SUFFIX;
		String templateName = "Controller.ftl";

		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<>();
		generateFileByTemplate(templateName, mapperFile, dataMap);

		// 生成网关Controller
		String gatePath = diskGatePath + "controller//" + modelName + "Controller"  + SUFFIX;
		templateName = "GateController.ftl";
		File gateFile = new File(gatePath);
		dataMap.clear();
		generateFileByTemplate(templateName, gateFile, dataMap);
	}

	private void generateServiceFile() throws Exception {
		String path = diskServerPath + "service//" + modelName + "Service" + SUFFIX;
		String templateName = isDB ? "Service.ftl" : "ServiceForES";

		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<>();
		generateFileByTemplate(templateName, mapperFile, dataMap);

		// 生成网关Service
		String gatePath = diskGatePath + "service//" + modelName + "Service" + SUFFIX;
		templateName = "GateService.ftl";
		File gateFile = new File(gatePath);
		dataMap.clear();
		generateFileByTemplate(templateName, gateFile, dataMap);
	}

	private void generateRepositoryFile() throws Exception {
		final String path = diskServerPath + "mysql//repository//" + modelName + "Repository" + SUFFIX;
		final String templateName = isDB ? "Repository.ftl" : "RepositoryForES.ftl";

		File dirPath = new File(diskServerPath + "mysql//repository");
		if (!dirPath.exists()) {
			dirPath.mkdirs();
		}

		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateFileByTemplate(final String templateName, File file, Map<String, Object> dataMap)
			throws Exception {
		Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
		FileOutputStream fos = new FileOutputStream(file);
		Object table_name = dataMap.get("table_name");
		dataMap.put("table_name", table_name ==null ?tableName:table_name.toString());
		Object model_name = dataMap.get("model_name");
		dataMap.put("model_name", model_name == null?modelName:model_name.toString());
		dataMap.put("author", AUTHOR);
		dataMap.put("date", CURRENT_DATE);
		dataMap.put("package_name", packageName);
		Object table_annotation = dataMap.get("table_annotation");
		dataMap.put("table_annotation", table_annotation == null?tableAnnotation:table_annotation.toString());
		Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
		template.process(dataMap, out);
	}

	public static String replaceUnderLineAndUpperCase(String str) {
		StringBuffer sb = new StringBuffer();
		sb.append(str);
		int count = sb.indexOf("_");
		while (count != 0) {
			int num = sb.indexOf("_", count);
			count = num + 1;
			if (num != -1) {
				char ss = sb.charAt(count);
				char ia = (char) (ss - 32);
				sb.replace(count, count + 1, ia + "");
			}
		}
		String result = sb.toString().replaceAll("_", "");
		return StringUtils.capitalize(result);
	}
}
